package Java_Lab.Multithreading.ThreadPool;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ThreadPoolFactory {
	
	public static ThreadPool getThreadPool(){
		return getThreadPool(ThreadPoolImpl.DEFAULT_NUMBER_OF_THREADS);
	}
	
	public static ThreadPool getThreadPool(int numberOfThreads){
		return new ThreadPoolImpl(numberOfThreads);
	}
	
	private static class ThreadPoolImpl implements ThreadPool{
		
		private static final int DEFAULT_NUMBER_OF_THREADS = 5;
		
		private int threads;
		
		private int activeThreads = 0;
		
		private List<Runnable> tasks;
		
		private Iterator<Runnable> taskIterator;
		
		private ThreadCompleteListener listener = new ThreadCompleteListener() {
			public void notifyOfThreadComplete() {
				activeThreads--;
				startNext();
			}
		};
		
		public ThreadPoolImpl(int numberOfThreads) {
			threads = numberOfThreads;
			tasks = new ArrayList<Runnable>();
		}

		public void execute() {
			startNext();
		}

		public void addTask(Runnable task) {
			tasks.add(task);
		}

		public void removeTask(Runnable task) {
			tasks.remove(task);
		}

		public int getNumberOfThreads() {
			return threads;
		}
		
		private synchronized void startNext(){
			if(taskIterator == null) taskIterator = tasks.iterator();
			while(activeThreads < threads && taskIterator.hasNext()){
				activeThreads++;
				new NotifyingThread(taskIterator.next(), listener).start();
			}
		}
	}
	
	public static void main(String[] str){
		ThreadPool pool = ThreadPoolFactory.getThreadPool();
		for(int i = 0; i < 10; i++)
			pool.addTask(new Worker("Worker " + i));
		pool.execute();
	}
}
